/**
 * 文件上传服务层
 */
const path = require('path');
const fs = require('fs').promises;
const crypto = require('crypto');
const { validateFileType, validateFileSize } = require('../utils/validation');

/**
 * 处理头像上传服务
 * @param {Object} file - 上传的文件对象
 * @param {number} userId - 用户ID
 * @returns {Object} 上传结果
 */
const uploadAvatar = async (file, userId) => {
  if (!file) {
    throw new Error('请选择要上传的头像文件');
  }

  // 验证文件类型
  const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'];
  if (!validateFileType(file.mimetype, allowedTypes)) {
    throw new Error('头像文件格式不支持，请上传 JPG、PNG 或 GIF 格式的图片');
  }

  // 验证文件大小 (5MB)
  const maxSize = 5 * 1024 * 1024;
  if (!validateFileSize(file.size, maxSize)) {
    throw new Error('头像文件大小不能超过 5MB');
  }

  // 生成文件名
  const fileExtension = path.extname(file.originalname);
  const fileName = `avatar_${userId}_${Date.now()}${fileExtension}`;
  const uploadPath = path.join('uploads', 'avatars', fileName);

  try {
    // 确保上传目录存在
    await ensureDirectoryExists(path.dirname(uploadPath));

    // 保存文件
    await fs.writeFile(uploadPath, file.buffer);

    // 生成访问URL
    const fileUrl = `/uploads/avatars/${fileName}`;

    return {
      success: true,
      fileName,
      filePath: uploadPath,
      fileUrl,
      fileSize: file.size,
      mimeType: file.mimetype,
      uploadedAt: new Date()
    };
  } catch (error) {
    throw new Error(`头像上传失败: ${error.message}`);
  }
};

/**
 * 处理音频文件上传服务
 * @param {Object} file - 上传的文件对象
 * @param {number} userId - 用户ID
 * @returns {Object} 上传结果
 */
const uploadAudio = async (file, userId) => {
  if (!file) {
    throw new Error('请选择要上传的音频文件');
  }

  // 验证文件类型
  const allowedTypes = ['audio/mpeg', 'audio/mp3', 'audio/wav', 'audio/ogg', 'audio/m4a'];
  if (!validateFileType(file.mimetype, allowedTypes)) {
    throw new Error('音频文件格式不支持，请上传 MP3、WAV、OGG 或 M4A 格式的音频');
  }

  // 验证文件大小 (10MB)
  const maxSize = 10 * 1024 * 1024;
  if (!validateFileSize(file.size, maxSize)) {
    throw new Error('音频文件大小不能超过 10MB');
  }

  // 生成文件名
  const fileExtension = path.extname(file.originalname);
  const fileName = `audio_${userId}_${Date.now()}${fileExtension}`;
  const uploadPath = path.join('uploads', 'audio', fileName);

  try {
    // 确保上传目录存在
    await ensureDirectoryExists(path.dirname(uploadPath));

    // 保存文件
    await fs.writeFile(uploadPath, file.buffer);

    // 提取音频元数据（这里是简化版本，实际可能需要使用专门的音频处理库）
    const metadata = await extractAudioMetadata(uploadPath);

    // 生成访问URL
    const fileUrl = `/uploads/audio/${fileName}`;

    return {
      success: true,
      fileName,
      filePath: uploadPath,
      fileUrl,
      fileSize: file.size,
      mimeType: file.mimetype,
      duration: metadata.duration,
      uploadedAt: new Date()
    };
  } catch (error) {
    throw new Error(`音频上传失败: ${error.message}`);
  }
};

/**
 * 处理文档上传服务
 * @param {Object} file - 上传的文件对象
 * @param {number} userId - 用户ID
 * @returns {Object} 上传结果
 */
const uploadDocument = async (file, userId) => {
  if (!file) {
    throw new Error('请选择要上传的文档文件');
  }

  // 验证文件类型
  const allowedTypes = [
    'application/pdf',
    'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'application/vnd.ms-excel',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'text/plain'
  ];
  if (!validateFileType(file.mimetype, allowedTypes)) {
    throw new Error('文档格式不支持，请上传 PDF、DOC、DOCX、XLS、XLSX 或 TXT 格式的文件');
  }

  // 验证文件大小 (20MB)
  const maxSize = 20 * 1024 * 1024;
  if (!validateFileSize(file.size, maxSize)) {
    throw new Error('文档文件大小不能超过 20MB');
  }

  // 生成文件名
  const fileExtension = path.extname(file.originalname);
  const fileName = `doc_${userId}_${Date.now()}${fileExtension}`;
  const uploadPath = path.join('uploads', 'documents', fileName);

  try {
    // 确保上传目录存在
    await ensureDirectoryExists(path.dirname(uploadPath));

    // 保存文件
    await fs.writeFile(uploadPath, file.buffer);

    // 生成访问URL
    const fileUrl = `/uploads/documents/${fileName}`;

    return {
      success: true,
      fileName,
      filePath: uploadPath,
      fileUrl,
      fileSize: file.size,
      mimeType: file.mimetype,
      originalName: file.originalname,
      uploadedAt: new Date()
    };
  } catch (error) {
    throw new Error(`文档上传失败: ${error.message}`);
  }
};

/**
 * 处理通用文件上传服务
 * @param {Object} file - 上传的文件对象
 * @param {number} userId - 用户ID
 * @param {Object} options - 上传选项
 * @returns {Object} 上传结果
 */
const uploadFile = async (file, userId, options = {}) => {
  if (!file) {
    throw new Error('请选择要上传的文件');
  }

  const {
    allowedTypes = [],
    maxSize = 10 * 1024 * 1024, // 默认10MB
    uploadDir = 'general'
  } = options;

  // 验证文件类型
  if (allowedTypes.length > 0 && !validateFileType(file.mimetype, allowedTypes)) {
    throw new Error(`文件格式不支持，允许的格式: ${allowedTypes.join(', ')}`);
  }

  // 验证文件大小
  if (!validateFileSize(file.size, maxSize)) {
    const maxSizeMB = Math.round(maxSize / (1024 * 1024));
    throw new Error(`文件大小不能超过 ${maxSizeMB}MB`);
  }

  // 生成文件名
  const fileExtension = path.extname(file.originalname);
  const fileName = `${uploadDir}_${userId}_${Date.now()}${fileExtension}`;
  const uploadPath = path.join('uploads', uploadDir, fileName);

  try {
    // 确保上传目录存在
    await ensureDirectoryExists(path.dirname(uploadPath));

    // 保存文件
    await fs.writeFile(uploadPath, file.buffer);

    // 生成访问URL
    const fileUrl = `/uploads/${uploadDir}/${fileName}`;

    return {
      success: true,
      fileName,
      filePath: uploadPath,
      fileUrl,
      fileSize: file.size,
      mimeType: file.mimetype,
      originalName: file.originalname,
      uploadedAt: new Date()
    };
  } catch (error) {
    throw new Error(`文件上传失败: ${error.message}`);
  }
};

/**
 * 删除文件服务
 * @param {string} filePath - 文件路径
 * @returns {Object} 删除结果
 */
const deleteFile = async (filePath) => {
  try {
    await fs.access(filePath);
    await fs.unlink(filePath);
    
    return {
      success: true,
      message: '文件删除成功'
    };
  } catch (error) {
    if (error.code === 'ENOENT') {
      return {
        success: true,
        message: '文件不存在或已被删除'
      };
    }
    throw new Error(`文件删除失败: ${error.message}`);
  }
};

/**
 * 获取文件信息服务
 * @param {string} filePath - 文件路径
 * @returns {Object} 文件信息
 */
const getFileInfo = async (filePath) => {
  try {
    const stats = await fs.stat(filePath);
    const fileName = path.basename(filePath);
    const fileExtension = path.extname(filePath);
    
    return {
      fileName,
      fileSize: stats.size,
      fileExtension,
      createdAt: stats.birthtime,
      modifiedAt: stats.mtime,
      isDirectory: stats.isDirectory(),
      isFile: stats.isFile()
    };
  } catch (error) {
    throw new Error(`获取文件信息失败: ${error.message}`);
  }
};

/**
 * 确保目录存在（辅助函数）
 * @param {string} dirPath - 目录路径
 */
const ensureDirectoryExists = async (dirPath) => {
  try {
    await fs.access(dirPath);
  } catch (error) {
    if (error.code === 'ENOENT') {
      await fs.mkdir(dirPath, { recursive: true });
    } else {
      throw error;
    }
  }
};

/**
 * 提取音频元数据（辅助函数）
 * @param {string} filePath - 音频文件路径
 * @returns {Object} 音频元数据
 */
const extractAudioMetadata = async (filePath) => {
  // 这里是简化版本，实际应用中可能需要使用 ffprobe 或其他音频处理库
  // 来提取真实的音频元数据（时长、比特率、采样率等）
  
  try {
    const stats = await fs.stat(filePath);
    
    // 简单估算音频时长（这只是示例，不准确）
    // 实际应用中应该使用专门的音频处理库
    const estimatedDuration = Math.round(stats.size / (128 * 1024 / 8)); // 假设128kbps
    
    return {
      duration: estimatedDuration,
      fileSize: stats.size,
      bitrate: 128, // 假设值
      sampleRate: 44100 // 假设值
    };
  } catch (error) {
    return {
      duration: 0,
      fileSize: 0,
      bitrate: 0,
      sampleRate: 0
    };
  }
};

/**
 * 生成安全的文件名（辅助函数）
 * @param {string} originalName - 原始文件名
 * @param {number} userId - 用户ID
 * @returns {string} 安全的文件名
 */
const generateSafeFileName = (originalName, userId) => {
  const fileExtension = path.extname(originalName);
  const timestamp = Date.now();
  const randomString = crypto.randomBytes(8).toString('hex');
  
  return `${userId}_${timestamp}_${randomString}${fileExtension}`;
};

module.exports = {
  uploadAvatar,
  uploadAudio,
  uploadDocument,
  uploadFile,
  deleteFile,
  getFileInfo
};
